package org.example.sentinel.controller;

import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@ControllerAdvice // 使用当前类配置异常拦截
@RequestMapping("test")
public class TestController {

    @GetMapping
    @SentinelResource(
            value = "test",  // 资源名称
            blockHandler = "testBlock",// 规则异常
            blockHandlerClass = TestFallbackHandler.class,
            fallback = "testFallback", // 业务异常降级
            fallbackClass = TestFallbackHandler.class,
            exceptionsToIgnore = {CustomException.class} // 忽略异常，比如自定义异常可能在@ControllerAdvice配置
    )
    public String test(String value) {
        if ("admin".equalsIgnoreCase(value)) {
            throw new CustomException("管理员不能操作");
        }
        // 模拟未知异常
        if (Math.random() > 0.8) {
            throw new RuntimeException("其他异常情况");
        }
        log.info("request test path :{}", value);
        return "访问成功";
    }

    /**
     * 拦截CustomException异常
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public String handleCustomException(CustomException ex) {
        return "自定义异常：" + ex.getMessage();
    }

    /**
     * 自定义异常
     */
    public static class CustomException extends RuntimeException {
        public CustomException(String message) {
            super(message);
        }
    }


    /**
     * 熔断降级单独类处理
     */
    public static class TestFallbackHandler {
        /**
         * 规则熔断处理
         *
         * @param value 这里参数需要跟原参数对应，否则不能触发熔断方法
         * @param ex    必须有异常参数
         */
        public static String testBlock(String value, BlockException ex) {
            return "当前访问过于频繁，请稍后再试";
        }

        /**
         * 业务降级处理
         *
         * @param value 这里参数需要跟原参数对应，否则不能触发熔断方法
         * @param ex    必须有异常参数
         */
        public static String testFallback(String value, Throwable ex) {
            log.warn("触发熔断降级，value={}, 异常类型: {}", value, ex.getClass().getName());
            return "降级处理：" + ex.getClass().getName();
        }
    }
}
